package org.example;


import java.util.HashMap;
import java.util.Map;

/*
 *  示例1：[a,b]=[c,d]
 *  示例2: [a, b=c, [d, e=c]]
 *
 *  语法:
 *  grammar NestedNameList;
 *  stat     : list EOF
 *           | assign EOF
 *           ;
 *
 *  assign   : list '=' list ;
 *
 *  list     : '[' elements ']' ;
 *  elements : element (',' element)* ;
 *  element  : NAME '=' NAME
 *           | NAME
 *           | list
 *           ;
 *
 *  NAME     : ('a'..'z' | 'A'..'Z')+ ;   // NAME含有至少一个字母
 * */
public class BacktrackParser extends Parser {

    private final Map<Integer, Integer> list_memo = new HashMap<>();

    public BacktrackParser(Lexer input) {
        super(input);
    }

    @Override
    protected void clearMemo() {
        list_memo.clear();
    }

    public void stat() throws RecognitionException {
        if (speculate_stat_alt1()) {
            list();
            match(Lexer.EOF_TYPE);
        } else if (speculate_stat_alt2()) {
            assign();
            match(Lexer.EOF_TYPE);
        } else {
            throw new NoViableAltException("期望stat，但是输入了: " + LT(1));
        }
    }

    private boolean speculate_stat_alt1() {
        System.out.println("预测分支1");
        boolean success = true;
        mark();
        try {
            list();
            match(Lexer.EOF_TYPE);
        } catch (RecognitionException e) {
            success = false;
        }
        release();
        return success;
    }

    private boolean speculate_stat_alt2() {
        System.out.println("预测分支2");
        boolean success = true;
        mark();
        try {
            assign();
            match(Lexer.EOF_TYPE);
        } catch (RecognitionException e) {
            success = false;
        }
        release();
        return success;
    }

    public void assign() {
        list();
        match(BacktrackLexer.EQUALS);
        list();
    }

    public void list() {
        if (isSpeculating() && alreadyParsedRule(list_memo)) {
            return;
        }

        boolean failed = false;
        int startTokenIndex = index();

        try {
            _list();
        } catch (RecognitionException re) {
            failed = true;
            throw re;
        } finally {
            // 回溯时，不管解析是否成功，都必须记录解析结果
            if (isSpeculating()) {
                memorize(list_memo, startTokenIndex, failed);
            }
        }
    }

    public void _list() throws RecognitionException {
        System.out.println("解析list规则，Token索引:" + index());
        match(BacktrackLexer.LBRACK);
        elements();
        match(BacktrackLexer.RBRACK);
    }

    public void elements() {
        element();
        while (LA(1) == BacktrackLexer.COMMA) {
            match(BacktrackLexer.COMMA);
            element();
        }
    }

    public void element() {
        if (LA(1) == BacktrackLexer.NAME && LA(2) == BacktrackLexer.EQUALS) {
            match(BacktrackLexer.NAME);
            match(BacktrackLexer.EQUALS);
            match(BacktrackLexer.NAME);
        } else if (LA(1) == BacktrackLexer.NAME) {
            match(BacktrackLexer.NAME);
        } else if (LA(1) == BacktrackLexer.LBRACK) {
            _list();
        } else {
            throw new Error("期望输入name、name=name或list，但是输入为: " + LA(1));
        }
    }

}
